#ifndef GUARD_big_int_h
#define GUARD_big_int_h

#include <utility>
#include <iostream>
#include <algorithm>
#include <string>

#include "optimized_vector.h"

struct big_int
{
   explicit big_int(std::string);
   big_int(long long number = 0);

   big_int operator -() const;
   big_int& operator +=(const big_int&);
   big_int& operator -=(const big_int&);
   big_int& operator *=(const big_int&);
   big_int& operator /=(const big_int&);
   big_int& operator %=(const big_int&);
   big_int& operator *=(int);
   big_int& operator <<=(size_t);
   big_int& operator >>=(size_t);
   std::pair<big_int, big_int> divide_with_remainer(const big_int& divider) const;
   bool is_negative() const;
   void swap(big_int&);

   bool operator ==(const big_int&) const;
   bool operator !=(const big_int&) const;
   bool operator >=(const big_int&) const;
   bool operator >(const big_int&) const;
   bool operator <=(const big_int&) const;
   bool operator <(const big_int&) const;

private:
   static const int BASE = 1000000000;
   static const size_t BASE_LENGTH = 9;

   optimized_vector digits_;
   bool is_negative_;

   friend std::istream& operator >>(std::istream&, big_int&);
   friend std::ostream& operator <<(std::ostream&, const big_int&);

   int compare_to(const big_int&) const;
   inline size_t get_size() const;
   void add_leading_zeroes(size_t new_size);
   void cut_leading_zeroes();
   static int binary_search(big_int border, big_int number);
};

std::istream& operator >>(std::istream&, big_int&);
std::ostream& operator <<(std::ostream&, const big_int&);

big_int operator >>(const big_int& a, int b);
big_int operator <<(const big_int& a, int b);
big_int operator +(const big_int&, const big_int&);
big_int operator -(const big_int& a, const big_int& b);
big_int operator *(const big_int& a, int b);
big_int operator *(const big_int& a, const big_int& b);
big_int operator /(const big_int& a, const big_int& b);
big_int operator %(const big_int& a, const big_int& b);
big_int abs(big_int&);
#endif